import json
import re
import time
from typing import Dict, List, Any, Optional

class FlowExecutor:
    def __init__(self, flow_definition: Dict[str, Any]):
        self.nodes = {node["id"]: node for node in flow_definition["nodes"]}
        self.edges = {}
        # 按源节点ID组织边
        for edge in flow_definition["edges"]:
            source = edge["source"]
            if source not in self.edges:
                self.edges[source] = []
            self.edges[source].append(edge)
        
        self.variables = {}  # 存储变量
        self.current_node_id = None  # 当前节点ID
        self.is_running = False  # 执行状态

    def find_start_node(self) -> int:
        """找到开始节点"""
        for node_id, node in self.nodes.items():
            if node["type"] == "start":
                return node_id
        raise ValueError("流程定义中未找到开始节点")

    def get_next_node(self, current_node_id: int) -> Optional[int]:
        """根据当前节点和条件获取下一个节点"""
        if current_node_id not in self.edges:
            return None
            
        outgoing_edges = self.edges[current_node_id]
        # 如果只有一条边，直接返回目标节点
        if len(outgoing_edges) == 1:
            return outgoing_edges[0]["target"]
            
        # 有多条边时，根据条件判断
        for edge in outgoing_edges:
            if "condition" in edge:
                condition = edge["condition"]
                # 简单的条件表达式求值（仅支持变量比较）
                try:
                    # 使用变量字典作为局部变量来求值
                    if eval(condition, {}, self.variables):
                        return edge["target"]
                except Exception as e:
                    print(f"条件表达式执行错误: {condition}, 错误: {e}")
                    
        return None

    def execute_node(self, node: Dict[str, Any]) -> None:
        """执行节点操作"""
        node_type = node["type"]
        node_id = node["id"]
        print(f"\n执行节点 {node_id}: {node.get('label', node.get('text', node_type))}")
        
        if node_type == "start":
            # 开始节点不需要特殊操作
            pass
            
        elif node_type == "setVar":
            # 设置变量
            var_name = node["varName"]
            value = node["value"]
            self.variables[var_name] = value
            print(f"设置变量: {var_name} = {value}")
            
        elif node_type == "write":
            # 执行写入命令
            command = node["command"]
            params = node.get("params", [])
            
            # 收集参数值
            param_values = {}
            for param in params:
                param_values[param["code"]] = param["value"]
                
            # 替换命令中的变量
            formatted_command = command.format(**param_values)
            print(f"发送命令: {formatted_command}")
            #print(f"参数: {', '.join([f'{p["name"]}={p["value"]}' for p in params])}")
            print(f"参数: {params}")
            
        elif node_type == "sleep":
            # 休眠（模拟，实际可以缩短时间）
            duration = node["value"]
            print(f"休眠 {duration}ms (模拟执行)")
            # 实际执行可以取消下面这行的注释
            # time.sleep(duration / 1000)
            
        elif node_type == "read":
            # 执行读取命令
            command = node["command"]
            params = node.get("params", [])
            
            # 收集输入参数值
            param_values = {}
            in_params = []
            out_params = []
            
            for param in params:
                if param["category"] == "in":
                    param_values[param["code"]] = param["value"]
                    in_params.append(param)
                else:
                    out_params.append(param)
            
            # 替换命令中的变量
            formatted_command = command.format(** param_values)
            print(f"发送读取命令: {formatted_command}")
            #print(f"输入参数: {', '.join([f'{p["name"]}={p["value"]}' for p in in_params])}")
            #print(f"输入参数: {', '.join([f'{p["name"]}={p["value"]}' for p in in_params])}")
            
            # 模拟设备返回值
            mock_response = f"CH1:1.5V, 0.5A"  # 模拟返回值
            print(f"设备返回: {mock_response}")
            
            # 解析输出参数
            for param in out_params:
                regex = param["regex"]
                try:
                    # 尝试匹配正则表达式
                    match = re.search(regex, mock_response)
                    if match:
                        value = float(match.group(1))
                        self.variables[param["code"]] = value
                        print(f"解析参数 {param['name']}: {value}")
                    else:
                        print(f"无法解析参数 {param['name']}，正则: {regex}")
                except Exception as e:
                    print(f"解析参数 {param['name']} 错误: {e}")
                    
        elif node_type == "changeVar":
            # 修改变量
            var_name = node["varName"]
            change_value = node["value"]
            if var_name in self.variables:
                original_value = self.variables[var_name]
                # 简单的加操作（可以扩展为其他操作）
                self.variables[var_name] = original_value + change_value
                print(f"更新变量: {var_name} 从 {original_value} 变为 {self.variables[var_name]}")
            else:
                print(f"警告: 变量 {var_name} 未定义")
                
        elif node_type == "end":
            # 结束节点
            print("流程执行结束")
            self.is_running = False

    def run(self) -> None:
        """运行流程"""
        try:
            self.current_node_id = self.find_start_node()
            self.is_running = True
            print("开始执行流程...")
            
            while self.is_running and self.current_node_id is not None:
                current_node = self.nodes.get(self.current_node_id)
                if not current_node:
                    print(f"错误: 找不到节点 {self.current_node_id}")
                    break
                    
                # 执行当前节点
                self.execute_node(current_node)
                
                # 如果是结束节点，直接退出
                if current_node["type"] == "end":
                    break
                    
                # 获取下一个节点
                self.current_node_id = self.get_next_node(self.current_node_id)
                
                if self.current_node_id is None:
                    print("流程中断，找不到下一个节点")
                    self.is_running = False
                    
        except Exception as e:
            print(f"流程执行错误: {e}")
            self.is_running = False

if __name__ == "__main__":
    # 流程定义（与题目中提供的一致）
    flow_definition = {
        "nodes": [
            {"id": 1, "type": "start", "label": "开始"},
            {"id": 2, "type": "setVar", "label": "设置变量 循环次数", "varName": "index", "value": 1},
            {"id": 3, "type": "write", "text": "设置电压电流", "command": ":APPL {{channel}},{{voltage}}", "params": [
                {"category": "in", "code": "channel", "name": "通道", "type": "string", "value": "1"}, 
                {"category": "in", "code": "voltage", "name": "电压", "type": "number", "value": 1.5}, 
                {"category": "in", "code": "current", "name": "电流", "type": "number", "value": 0.5}
            ]},
            {"id": 4, "type": "sleep", "label": "休眠500ms", "varName": "index", "value": 500},
            {"id": 5, "type": "read", "text": "读取电压电流", "command": ":APPL? {{channel}}", "params": [
                {"category": "in", "code": "channel", "name": "通道", "type": "string", "value": "1"}, 
                {"category": "out", "code": "voltage", "name": "电压", "type": "number", "regex": "CH1:(\\d+\\.\\d+)V"}, 
                {"category": "out", "code": "current", "name": "电流", "type": "number", "regex": "(\\d+\\.\\d+)A"}
            ]},
            {"id": 6, "type": "changeVar", "text": "更新变量 循环次数++", "varName": "index", "value": 1},
            {"id": 7, "type": "end", "text": "结束"}
        ],
        "edges": [
            {"source": 1, "target": 2, "text": ""},
            {"source": 2, "target": 3, "text": ""},
            {"source": 3, "target": 4, "text": ""},
            {"source": 4, "target": 5, "text": ""},
            {"source": 5, "target": 6, "text": ""},
            {"source": 6, "target": 3, "text": "循环次数<=10", "condition": "index<10"},
            {"source": 6, "target": 7, "text": "循环次数>=10", "condition": "index>=10"}
        ]
    }
    
    # 创建执行器并运行流程
    executor = FlowExecutor(flow_definition)
    executor.run()
    
    # 打印最终变量状态
    print("\n最终变量状态:", executor.variables)
